#include "cgzCTcpWC.h"
#include "cgzCTcpGateWS.h"
#include "cgzCThreadPool.h"

cgzCTcpGateWS::cgzCTcpGateWS(
    cgzCThreadPool *pool,
    const char *name,
    const std::string ip,
    const int port,
    const int cid,
    const bool gate)
    : cgzCTcpWS(pool, name, ip, port, cid),
      m_gate(gate)
{
    m_tenum = cgzETask::CTcpGateWS;
}

cgzCTcpGateWS::~cgzCTcpGateWS()
{
}

bool cgzCTcpGateWS::decodeProc(cgzCTcpFd *fdinfo, cgzCWDecode &de)
{
    if (m_gate)
    {
        char *data = de.decode_data;
        cgzGateHeader &header = *(cgzGateHeader *)data;
        todoret(fdinfo, header);
    }
    else
    {
        char *data = de.decode_data;
        cgzHeader &header = *(cgzHeader *)data;
        todoret(fdinfo, header);
    }
    return true;
}

// 收到客户端消息
bool cgzCTcpGateWS::todoret(cgzCTcpFd *fdinfo, cgzHeader &header)
{
    // 更改消息目标
    auto it = m_gates.find(header.mid);
    if (it != m_gates.end())
    {
        auto target = it->second;
        auto itt = m_pool->getTask(target);
        if (!itt)
        {
            return false;
        }
        switch (itt->getTEnum())
        {
        case cgzETask::CTcpGateC:
        {
            // 网关收到客户端消息-转发给服务端
            void *node = malloc(sizeof(cgzCSendC));
            auto send = new (node) cgzCSendC(header, fdinfo->m_ufd);
            auto skipHead = sizeof(cgzHeader);
            auto copyLen = header.all - skipHead;
            auto copyData = send->m_data + sizeof(cgzGateHeader);
            fdinfo->m_recv.pop(skipHead);
            fdinfo->m_recv.read(copyData, copyLen);
            fdinfo->m_recv.pop(copyLen);

            send->target = target;
            send->origin = getId();
            cgzCTcpWS::todoret(send);
            return true;
        };
        case cgzETask::CTcpGateWC:
        {
            // 网关收到客户端消息-转发给服务端
            void *node = malloc(sizeof(cgzCSendWC));
            auto send = new (node) cgzCSendWC(header, fdinfo->m_ufd);
            auto skipHead = sizeof(cgzHeader);
            auto copyLen = header.all - skipHead;
            auto copyData = send->m_data + sizeof(cgzGateHeader);
            fdinfo->m_recv.pop(skipHead);
            fdinfo->m_recv.read(copyData, copyLen);
            fdinfo->m_recv.pop(copyLen);

            send->target = target;
            send->origin = getId();
            cgzCTcpWS::todoret(send);
            return true;
        }
        break;
        default:
        {
            // 异常消息
            cgz_this_error("{} task not found, mid={} ", m_name, header.mid);
        }
        break;
        }
    }
    else
    {
        cgz_this_error("{} gate not found, mid={}", m_name, header.mid);
    }
    return false;
}

// 收到网关转发消息
bool cgzCTcpGateWS::todoret(cgzCTcpFd *fdinfo, cgzGateHeader &header)
{
    // 服务端收到网关消息-转发给逻辑线程
    void *node = malloc(sizeof(cgzCRecvS));
    auto recv = new (node) cgzCRecvS(header, fdinfo->m_ufd, fdinfo->m_fd);
    fdinfo->m_recv.read(recv->m_data, header.all);
    fdinfo->m_recv.pop(header.all);
    recv->target = m_cid;
    recv->origin = getId();
    cgzCTcpS::todoret(recv);
    return true;
}

bool cgzCTcpGateWS::run(cgzCLoopS *task)
{
    switch (task->getEType())
    {
    case ETCP_S::TCPS_GADD:
    {
        auto &map = static_cast<cgzCGAddS *>(task)->map;
        m_gates.insert(map.begin(), map.end());
    }
    break;
    case ETCP_S::TCPS_GDEL:
    {
        auto &set = static_cast<cgzCGDelS *>(task)->set;
        for (auto it : set)
        {
            auto eit = m_gates.find(it);
            if (eit != m_gates.end())
            {
                m_gates.erase(eit);
            }
        }
    }
    break;
    case ETCP_S::TCPS_GCLR:
    {
        m_gates.clear();
    }
    break;
    default:
    {
        assert(false);
    }
    }
    task->~cgzCLoopS();
    free(task);
    return true;
}